#pragma once

#include "Singleton.h"
#include "rpc/RPCManager.h"

class PacketDispatcher : private RPCActor, public Singleton<PacketDispatcher>
{
public:
	PacketDispatcher();
	virtual ~PacketDispatcher();

	void Tick();

	void SendPacket2Guild(const INetPacket &pck);
	void SendPacket2Rank(const INetPacket &pck);
	void SendPacket2Operating(const INetPacket &pck);

	void RPCInvoke2Guild(const INetPacket &pck,
		const std::function<void(INetStream&, int32, bool)> &cb = nullptr,
		AsyncTaskOwner *owner = nullptr, time_t timeout = DEF_S2S_RPC_TIMEOUT);
	void RPCInvoke2Rank(const INetPacket &pck,
		const std::function<void(INetStream&, int32, bool)> &cb = nullptr,
		AsyncTaskOwner *owner = nullptr, time_t timeout = DEF_S2S_RPC_TIMEOUT);
	void RPCInvoke2Operating(const INetPacket &pck,
		const std::function<void(INetStream&, int32, bool)> &cb = nullptr,
		AsyncTaskOwner *owner = nullptr, time_t timeout = DEF_S2S_RPC_TIMEOUT);

	void RPCReply(const INetPacket &pck,
		uint64 sn, int32 err = RPCErrorNone, bool eof = true);

	void RunS2SRPCReply(SocialRPCReply replyType, const INetPacket &rpcRespPck,
		uint64 sn, int32 err = RPCErrorNone, bool eof = true);

private:
	virtual void PushRPCPacket(const INetPacket &trans,
		const INetPacket &pck, const std::string_view &args);

	virtual RPCManager *GetRPCManager() {
		return &mgr_;
	}

	RPCManager mgr_;
};

#define sPacketDispatcher (*PacketDispatcher::instance())
